package com.boarsoft.dao.sharding.util;

import com.boarsoft.dao.sharding.bean.JdbcUrlInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 解析JDBC连接信息
 *
 */
public class JdbcUrlUtil {
    private static final Logger logger = LoggerFactory.getLogger(JdbcUrlUtil.class);

    /** MySQL */
    private static final String TYPE_MYSQL = "mysql";
    // jdbc:mysql://{host}[:{port}]/[{database}][\\?{params}]
    private static final String REGEX_MYSQL = "jdbc:mysql://(?<host>[a-zA-Z0-9-//.]+)(:(?<port>[0-9]+))?/(?<database>[a-zA-Z0-9_]+)?(\\?(?<params>[a-zA-Z0-9_&;=\\-_]+)?)?";

    /** PostgreSQL */
    private static final String TYPE_POSTGRESQL = "postgresql";
    // jdbc:postgresql://{host}[:{port}]/[{database}][\\?{params}]
    private static final String REGEX_POSTGRESQL = "jdbc:postgresql://(?<host>[a-zA-Z0-9-//.]+)(:(?<port>[0-9]+))?/(?<database>[a-zA-Z0-9_]+)?(\\?(?<params>[a-zA-Z0-9_&;=\\-_]+)?)?";

    /**
     * 解析JDBC连接信息
     *
     * @param url
     * @return
     */
    public static JdbcUrlInfo parseJdbcUrl(String url) {
        JdbcUrlInfo jdbcUrlInfo = new JdbcUrlInfo();
        if (url == null || "".equals(url.trim())) {
            throw new IllegalArgumentException("jdbc url is empty!");
        }

        String regex="jdbc:(?<type>[a-z]+):(\\S)*";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(url);
        String dbType = null;
        while (matcher.find()) {
            dbType = matcher.group("type");
        }
        if (dbType == null) {
            throw new IllegalArgumentException(String.format("Unknown database type for url: %s", url));
        }

        switch (dbType) {
            case TYPE_MYSQL:
                parseJdbcUrl(REGEX_MYSQL, url, jdbcUrlInfo);
                break;
            case TYPE_POSTGRESQL:
                parseJdbcUrl(REGEX_POSTGRESQL, url, jdbcUrlInfo);
                break;
            default:
                //
        }

        jdbcUrlInfo.setDbType(dbType);
        return jdbcUrlInfo;
    }

    /**
     * 解析JDBC URL
     *
     * @param regex
     * @param url
     * @param info
     */
    private static void parseJdbcUrl(String regex, String url, JdbcUrlInfo info) {
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(url);
        while (matcher.find()) {
            info.setHost(matcher.group("host"));
            info.setPort(matcher.group("port"));
            info.setDatabase(matcher.group("database"));
            try {
                String params = matcher.group("params");
                if (params != null && !"".equals(params.trim())) {
                    String[] paramArr = params.split(";|&");
                    for (String param: paramArr) {
                        String[] kv = param.split("=");
                        info.getParams().put(kv[0], kv[1]);
                    }
                }
            } catch (Exception e) {
                logger.error("parse params ex, url: {}, ex: {}", url, e.getMessage(), e);
            }
        }
    }
}